home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / CH_4.1 / MORPH / MORPH.C < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-11  |  7.4 KB  |  263 lines

  1. /* 
  2.  * morph.c
  3.  * 
  4.  * Practical Algorithms for Image Analysis
  5.  * 
  6.  * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
  7.  */
  8.  
  9. /* MORPH:       performs erosion, dilation, opening, closing with
  10.  *                    square structuring element of size kxk
  11.  *
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17. #include <tiffimage.h>          /* picfile info on images */
  18. #include <images.h>
  19. extern void print_sos_lic ();
  20.  
  21. #define ON 255                  /* binarization values */
  22. #define OFF 0
  23. #define NITER_DFLT 1            /* default threshold on number iteratoins */
  24. #define SIZE_DFLT 3             /* default size of structuring element */
  25.  
  26. int input (int, char **, long *, long *, long *, long *);
  27. int usage (short);
  28.  
  29. int argc;
  30. char *argv[];
  31. long *nIter;                    /* number of iterations to perform */
  32. long *opType;                   /* operation type */
  33. long *size;
  34.  
  35.  
  36. main (argc, argv)
  37.      int argc;
  38.      char *argv[];
  39.  
  40. {
  41.   Image *imgI, *imgO;           /* input and output image structures */
  42.   unsigned char **imgIn, **imgOut;  /* input and output image arrays */
  43.   long width, height;           /* size of image */
  44.   long nIter;                   /* number of iterations to perform */
  45.   long opType;                  /* operation type */
  46.   long size;                    /* structuring element size (must be odd) */
  47.   long invertFlag;              /* invert input image before processing */
  48.   long sizeD2;                  /* half structuring element size */
  49.   long xEnd, yEnd;              /* end of image within 1-pixel borders */
  50.   long sum;                     /* sum of ON pixels in neighborhood */
  51.   long sumAll;                  /* sum of (size x size) */
  52.   long nChange;                 /* number pixels changed on iteration */
  53.   long x, y, i, j, n;
  54.  
  55. /* user input */
  56.   if ((input (argc, argv, &nIter, &opType, &size, &invertFlag)) < 0)
  57.     return (-1);
  58.   sizeD2 = size / 2;
  59.  
  60. /* open input and output image */
  61.   imgI = ImageIn (argv[1]);
  62.   imgIn = ImageGetPtr (imgI);
  63.   height = ImageGetHeight (imgI);
  64.   width = ImageGetWidth (imgI);
  65.   printf ("Input mage size is %dx%d.\n", width, height);
  66.  
  67.   imgO = ImageAlloc (height, width, 8);
  68.   imgOut = ImageGetPtr (imgO);
  69.  
  70. /* invert image */
  71.   if (invertFlag) {
  72.     for (y = 0; y < height; y++)
  73.       for (x = 0; x < width; x++)
  74.       imgIn[y][x] = 255 - imgIn[y][x];
  75.   }
  76.  
  77. /* zero image borders */
  78.   yEnd = height - sizeD2;
  79.   xEnd = width - sizeD2;
  80.   for (y = 0; y < height; y++) {
  81.     for (x = 0; x <= sizeD2; x++)
  82.       imgIn[y][x] = OFF;
  83.     for (x = xEnd - 1; x < width; x++)
  84.       imgIn[y][x] = OFF;
  85.   }
  86.   for (x = 0; x < width; x++) {
  87.     for (y = 0; y <= sizeD2; y++)
  88.       imgIn[y][x] = OFF;
  89.     for (y = yEnd - 1; y < height; y++)
  90.       imgIn[y][x] = OFF;
  91.   }
  92.  
  93. /* write input to output image */
  94.   for (y = 0; y < height; y++)
  95.     for (x = 0; x < width; x++)
  96.       imgOut[y][x] = imgIn[y][x];
  97.  
  98. /* perform morphological iterations */
  99.   sumAll = size * size;
  100.   for (n = 0; n < nIter; n++) {
  101.     nChange = 0;
  102.     for (y = sizeD2; y < yEnd; y++) {
  103.       for (x = sizeD2; x < xEnd; x++) {
  104.         sum = 0;
  105.         for (i = -sizeD2; i <= sizeD2; i++)
  106.           for (j = -sizeD2; j <= sizeD2; j++)
  107.             sum += (imgIn[y + i][x + j] > 0) ? 1 : 0;
  108.  
  109.         switch (opType) {
  110.         case 1:                /* dilation */
  111.           if (sum > 0) {
  112.             imgOut[y][x] = ON;
  113.             nChange++;
  114.           }
  115.           break;
  116.         case 2:                /* erosion */
  117.           if (sum < sumAll) {
  118.             imgOut[y][x] = OFF;
  119.             nChange++;
  120.           }
  121.           break;
  122.         case 3:                /* dilation-erosion */
  123.           if (sum > 0) {
  124.             imgOut[y][x] = ON;
  125.             nChange++;
  126.           }
  127.           break;
  128.         case 4:                /* erosion-dilation */
  129.           if (sum < sumAll) {
  130.             imgOut[y][x] = OFF;
  131.             nChange++;
  132.           }
  133.           break;
  134.         default:
  135.           usage (1);
  136.         }
  137.       }
  138.     }
  139.     printf ("iteration %d: nChange = %d\n", n, nChange);
  140.     for (y = 0; y < height; y++)
  141.       for (x = 0; x < width; x++)
  142.         imgIn[y][x] = imgOut[y][x];
  143.     if (opType == 4)
  144.       opType = 3;
  145.     else if (opType == 3)
  146.       opType = 4;
  147.   }
  148.  
  149. /* un-invert image */
  150.   if (invertFlag) {
  151.     for (y = 0; y < height; y++)
  152.       for (x = 0; x < width; x++)
  153.       imgOut[y][x] = 255 - imgOut[y][x];
  154.   }
  155.  
  156.   ImageOut (argv[2], imgO);
  157.  
  158.   return (0);
  159. }
  160.  
  161.  
  162.  
  163. /* USAGE:       function gives instructions on usage of program
  164.  *                    usage: usage (flag)
  165.  *              When flag is 1, the long message is given, 0 gives short.
  166.  */
  167.  
  168. int
  169. usage (flag)
  170.      short flag;                /* flag =1 for long message; =0 for short message */
  171. {
  172.  
  173. /* print short usage message or long */
  174.   printf ("USAGE: morph inimg outimg [-i ITERATIONS] [-o OPERATION]\n");
  175.   printf ("                          [-s SIZE] [-I] [-L]\n");
  176.   if (flag == 0)
  177.     return (-1);
  178.  
  179.   printf ("\nmorph performs morphological processing on binary image\n\n");
  180.   printf ("ARGUMENTS:\n");
  181.   printf ("    inimg: input image filename (TIF)\n");
  182.   printf ("   outimg: output image filename (TIF)\n\n");
  183.   printf ("OPTIONS:\n");
  184.   printf ("  -i ITERATIONS: number of iterations to perform.\n");
  185.   printf ("                (default = %d)\n", NITER_DFLT);
  186.   printf ("   -o OPERATION: for dilation(1), erosion(2), closing(3),\n");
  187.   printf ("                 or opening(4) (default = 1).\n");
  188.   printf ("                 closing operation is alternating dilation-erosion;\n");
  189.   printf ("                 opening operation is alternating erosion-dilation;\n");
  190.   printf ("                 for opening or closing, the number of iterations is\n");
  191.   printf ("                 the sum of the comprising dilation and erosion iterations.\n");
  192.   printf ("        -s SIZE: size of structuring element -- must be odd and >=3\n");
  193.   printf ("                 (default = %d)\n", SIZE_DFLT);
  194.   printf ("             -I: invert input image before processing\n");
  195.   printf ("             -L: print Software License for this module\n");
  196.  
  197.   return (-1);
  198. }
  199.  
  200.  
  201. /* INPUT:       function reads input parameters
  202.  *                  usage: input (argc, argv, &nIter, &opType, &size);
  203.  */
  204.  
  205. #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
  206.  
  207. int
  208. input (argc, argv, nIter, opType, size, invertFlag)
  209.      int argc;
  210.      char *argv[];
  211.      long *nIter;               /* number of iterations to perform */
  212.      long *opType;              /* operation type */
  213.      long *size;                /* size of structuring element */
  214.      long *invertFlag;          /* size of structuring element */
  215. {
  216.   long n;
  217.  
  218.   if (argc == 1)
  219.     USAGE_EXIT (1);
  220.   if (argc == 2)
  221.     USAGE_EXIT (0);
  222.  
  223.   *nIter = NITER_DFLT;
  224.   *opType = 1;
  225.   *size = SIZE_DFLT;
  226.   *invertFlag = 0;
  227.  
  228.   for (n = 3; n < argc; n++) {
  229.     if (strcmp (argv[n], "-i") == 0) {
  230.       if (++n == argc || argv[n][0] == '-')
  231.         USAGE_EXIT (0);
  232.       *nIter = atol (argv[n]);
  233.     }
  234.     else if (strcmp (argv[n], "-o") == 0) {
  235.       if (++n == argc || argv[n][0] == '-')
  236.         USAGE_EXIT (0);
  237.       *opType = atol (argv[n]);
  238.     }
  239.     else if (strcmp (argv[n], "-s") == 0) {
  240.       if (++n == argc || argv[n][0] == '-')
  241.         USAGE_EXIT (0);
  242.       *size = atol (argv[n]);
  243.     }
  244.     else if (strcmp (argv[n], "-I") == 0)
  245.       *invertFlag = 1;
  246.     else if (strcmp (argv[n], "-L") == 0) {
  247.       print_sos_lic ();
  248.       exit (0);
  249.     }
  250.     else
  251.       USAGE_EXIT (0);
  252.   }
  253.  
  254.   if (*size < 3)
  255.     *size = 3;
  256.   if ((*size % 2) == 0) {
  257.     *size -= 1;
  258.     printf ("Structuring element size must be odd, set to %d\n", *size);
  259.   }
  260.  
  261.   return (0);
  262. }
  263.